Skip to content

upgrade: props package upgrade for Solid 2.0#908

Open
davedbase wants to merge 5 commits into
solidjs-community:nextfrom
davedbase:update/v2/props
Open

upgrade: props package upgrade for Solid 2.0#908
davedbase wants to merge 5 commits into
solidjs-community:nextfrom
davedbase:update/v2/props

Conversation

@davedbase
Copy link
Copy Markdown
Member

@davedbase davedbase commented May 21, 2026

Summary

Upgrades the props package to solid-js@^2.0.0-beta.13 / @solidjs/web@^2.0.0-beta.13 and adds two new utilities: combineHandlers and partitionProps.


Breaking changes

Peer dependencies updated
solid-js@^2.0.0-beta.13 and @solidjs/web@^2.0.0-beta.13 are now required.

classList support removed
Solid 2.0 removes the classList JSX prop in favour of class accepting objects and arrays. combineProps no longer handles a classList key. Pass an object or array as class instead:

// Before
combineProps(props, { classList: { active: isActive() } })
// After
combineProps(props, { class: { active: isActive() } })

class combining semantics updated
When all combined class values are strings they are joined with a space (unchanged). When any value is a ClassList object or array the result is a flat array, which Solid 2.0's class prop accepts natively.

merge replaces mergeProps semantics
Non-special props now follow merge semantics: an explicit undefined in a later source overrides earlier values (previously undefined was skipped).


New utilities

combineHandlers
Chains multiple event handlers into one. Handlers that are null, undefined, or false are silently skipped — useful for conditional handlers inline. Returns the single handler unchanged when only one is present (no wrapping overhead). Reactive through Solid's props proxy when used in JSX; for a standalone signal source, read it explicitly before passing or wrap the call in createMemo.

<button onClick={combineHandlers(props.onClick, internalHandler)} />
<div onKeyDown={combineHandlers(props.onKeyDown, isOpen() ? closeOnEsc : null)} />

partitionProps
Splits a props object into [matched, rest] — both views are lazy reactive proxies powered by filterProps under the hood, so the predicate runs per property read and both halves stay in sync with dynamic props. For an expensive predicate, pass a createPropsPredicate result to share a single cache across both views.

const [ownProps, htmlProps] = partitionProps(props,
  key => ["label", "variant", "size"].includes(key as string)
);
return <button {...htmlProps}>{ownProps.label}</button>;

Internal changes

  • mergePropsmerge, MergePropsMerge throughout
  • JSX type imported from @solidjs/web
  • createMemo(fn, undefined, options)createMemo(fn, options) (initialValue arg removed in 2.0)
  • Tests: createComputed replaced with createEffect(compute, apply) + flush(); signals created outside createRoot to avoid SIGNAL_WRITE_IN_OWNED_SCOPE
  • SSR test file added (test/server.test.ts)

Summary by CodeRabbit

  • New Features

    • Added combineHandlers and partitionProps helper utilities.
    • Updated to support Solid.js v2.0 (beta.13).
  • Breaking Changes

    • Removed classList JSX prop support; use class with objects/arrays instead.
    • Updated prop merging behavior to align with Solid 2.0 semantics where explicit undefined values override earlier values.

Review Change Stack

@davedbase davedbase added this to the Solid 2.0 Migration milestone May 21, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: 1e74307

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solid-primitives/props Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@davedbase davedbase marked this pull request as ready for review May 23, 2026 16:05
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 486416c2-b524-4658-a060-fe84cc24f91f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/props/README.md`:
- Around line 143-145: The README incorrectly describes filterProps as eager;
update the text to match the implementation by replacing the word "eagerly" with
"lazily" and rephrase the first sentence to state that filterProps splits props
lazily (per-read) rather than eagerly, and ensure the following sentence clearly
states that the predicate is executed on every property access and tracks
signals; reference the filterProps primitive and its predicate behavior so
readers know the predicate runs per property read and will re-run when tracked
signals change.

In `@packages/props/src/combineProps.ts`:
- Around line 178-188: The handling of class/className values in the
class-combining block pushes array-valued class entries into parts without
flattening, which can produce nested arrays; modify the branch that iterates
sources (the loop that reads access(s)[key] and pushes into parts) to detect
when v is an array (JSX.ClassList or string[]) and push its elements
individually (flatten one level) rather than the array itself so the final
returned value from the class/className handling (the parts variable) is a flat
array or joined string as before; update the logic that checks parts.length and
parts.every(...) to work unchanged with the flattened parts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 369c94d4-10ef-43cc-b8e7-81706e63b0c0

📥 Commits

Reviewing files that changed from the base of the PR and between 8e8ff1e and bf6ec8e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • .changeset/props-solid2-migration.md
  • packages/props/README.md
  • packages/props/dev/index.tsx
  • packages/props/package.json
  • packages/props/src/combineProps.ts
  • packages/props/src/filterProps.ts
  • packages/props/test/combineProps.test.ts
  • packages/props/test/filterProps.test.ts
  • packages/props/test/server.test.ts

Comment thread packages/props/README.md Outdated
Comment thread packages/props/src/combineProps.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant